// "Copyright [2021] <Copyright Shengkai Lin>"

#include <fstream>
#include <utility>
#include "cluster/basic/ai_sim.h"
#include "flowparser.h"

namespace ai_sim {
FormalCompoundIdx::FormalCompoundIdx(
    std::string str, std::map<int, std::string> levelnedmap) {
    std::size_t pos = str.find("(");
    // cout << "str" << str << endl;
    if (pos == std::string::npos) {
        modname = nullptr;
        index = -1;
        outpathidx = -1;
        return;
    }
    level = std::atoi(&str[pos + 1]);
    // cout << "level" << level << endl;
    modname = levelnedmap[level];
    string afterlevel = str.substr(pos + 3);
    pos = afterlevel.find(",");
    if (pos == std::string::npos) {
        index = -1;
        outpathidx = -1;
        return;
    }
    index = std::stoi(afterlevel.substr(0, pos));
    // cout << "index" << index << endl;
    string afterindex = afterlevel.substr(pos + 1);
    pos = afterindex.find(")");
    if (pos == std::string::npos) {
        outpathidx = -1;
        return;
    }
    outpathidx = std::stoi(afterindex.substr(0, pos));
    // cout << "outpathidx" << outpathidx << endl;
}

FlowParser::FlowParser(std::string file_path) {
    current_flow_pos = 0;
    std::ifstream input_file;
    input_file.open(file_path, std::ios::in);
    DetailFlow dflow;
    for (std::string line; std::getline(input_file, line, '\n'); ) {
        // cout << "line is: " << line << endl;
        if (line.substr(0, 2) == "//") continue;
        std::size_t levelname_ = line.find("levelname");
        std::size_t time_ = line.find("time");
        std::size_t datasize_ = line.find("datasize");
        std::size_t formal_ = line.find("compound");
        if (levelname_ != std::string::npos) {
            int level = std::atoi(&line[9]);
            std::size_t nednamepos = line.find("=");
            std::string nedname = line.substr(nednamepos + 1);
            // cout << "level:" << level << ",name:" << nedname << endl;
            levelnedmap[level] = nedname;
        } else if (time_ != std::string::npos) {
            // cout << "time: " << line.substr(5) << endl;
            dflow.time = std::stod(line.substr(5));
        } else if (datasize_ != std::string::npos) {
            // cout << "datasize: " << line.substr(9) << endl;
            dflow.data_size = std::stod(line.substr(9));
        } else if (formal_ != std::string::npos) {
            auto compound_ = FormalCompoundIdx(
                line.substr(9), levelnedmap);
            if (compound_.level != 0 && dflow.flow_path.empty()) {
                throw omnetpp::cRuntimeError(
                    "Should start a flow from level 0");
            }
            dflow.flow_path.push_back(compound_);
            if (compound_.level == 0 && dflow.flow_path.size() > 1) {
                flows.push_back(dflow);
                // throw omnetpp::cRuntimeError("stop");
                dflow.flow_path.clear();
            }
        }
    }
    if (!dflow.flow_path.empty())
        throw omnetpp::cRuntimeError("The last flow not ended with level 0");
}

DetailFlow FlowParser::getCurrentFlow() {
    if (flows.size() > current_flow_pos) {
        return flows[current_flow_pos];
    } else {
        return errflow;
    }
}

DetailFlow FlowParser::getNextFlow() {
    if (flows.size() > current_flow_pos + 1) {
        return flows[++current_flow_pos];
    } else {
        return errflow;
    }
}

}  // namespace ai_sim
